// ml278
// Copyright (C) 2008 Bjørn Øivind Bjørnsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

//
// Global variable definitions
//

uniform float fCameraHeightSqr;
uniform float fInnerRadius;
uniform float fKm4PI;
uniform float fKmESun;
uniform float fKr4PI;
uniform float fKrESun;
uniform float fOuterRadius;
uniform float fOuterRadiusSqr;
uniform float fScale;
uniform float fScaleOverScaleDepth;
uniform vec4 fvCameraPos;
uniform vec3 fvInvWavelengths;
uniform vec4 fvLightPos;
uniform mat4 matWorldViewProjection;

//
// Function declarations
//

float getNearIntersection( in vec3 v3Pos, in vec3 v3Ray, in float fDistance2, in float fRadius2 );
float scale( in float fCos );

//
// Function definitions
//

float getNearIntersection( in vec3 v3Pos, in vec3 v3Ray, in float fDistance2, in float fRadius2 ) {
    float B;
    float C;
    float fDet;

    B = (2.00000 * dot( v3Pos, v3Ray));
    C = (fDistance2 - fRadius2);
    fDet = max( 0.00000, ((B * B) - (4.00000 * C)));
    return (0.500000 * (( -B ) - sqrt( fDet )));
}


float scale( in float fCos ) {
    float x;

    x = (1.00000 - fCos);
    return (0.250000 * exp( (-0.00287000 + (x * (0.459000 + (x * (3.83000 + (x * (-6.80000 + (x * 5.25000)))))))) ));
}


void main() {
    vec3 fvPos;
    vec3 fvRay;
    float fFar;
    float fNear;
    vec3 fvStart;
    float fStartAngle;
    float fStartDepth;
    float fStartOffset;
    float fSampleLength;
    float fScaledLength;
    vec3 fvSampleRay;
    vec3 fvSamplePoint;
    vec3 fvFrontColor = vec3( 0.00000, 0.00000, 0.00000);
    int i;
    float fHeight;
    float fSampleDepth;
    float fLightAngle;
    float fCameraAngle;
    float fScatter;
    vec3 fvAttenuate;

    vec4 Position = vec4( gl_Vertex );
    fvPos = vec3( Position );
    fvRay = (fvPos - fvCameraPos.xyz );
    fvPos = normalize( fvPos );
    fFar = length( fvRay );
    fvRay /= fFar;
    fNear = getNearIntersection( vec3( fvCameraPos), fvRay, fCameraHeightSqr, fOuterRadiusSqr);
    fvStart = (vec3( fvCameraPos) + (fvRay * fNear));
    fFar -= fNear;
    fStartAngle = (dot( fvRay, fvStart) / fOuterRadius);
    fStartDepth = exp( -4.00000 );
    fStartOffset = (fStartDepth * scale( fStartAngle));
    fSampleLength = (fFar / 3.00000);
    fScaledLength = (fSampleLength * fScale);
    fvSampleRay = (fvRay * fSampleLength);
    fvSamplePoint = (fvStart + (fvSampleRay * 0.500000));
    for (i = 0 ; (i < 3); ( i++ )) {
        fHeight = length( fvSamplePoint );
        fSampleDepth = exp( (fScaleOverScaleDepth * (fInnerRadius - fHeight)) );
        fLightAngle = (dot( fvLightPos.xyz , fvSamplePoint) / fHeight);
        fCameraAngle = (dot( fvRay, fvSamplePoint) / fHeight);
        fScatter = (fStartOffset + (fSampleDepth * (scale( fLightAngle) - scale( fCameraAngle))));
        fvAttenuate = exp( (( -fScatter ) * ((fvInvWavelengths * fKr4PI) + fKm4PI)) );
        fvFrontColor += (fvAttenuate * (fSampleDepth * fScaledLength));
        fvSamplePoint += fvSampleRay;
    }

    gl_Position = vec4( matWorldViewProjection * Position );
    gl_TexCoord[0] = vec4( (fvFrontColor * (fvInvWavelengths * fKrESun)), 1.00000 );
    gl_TexCoord[1] = vec4( (fvFrontColor * fKmESun), 1.00000 );
    gl_TexCoord[2] = vec4( (fvCameraPos.xyz  - fvPos), 0.0 );
}



